#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

#define TOTAL 10
typedef unsigned long uint32 ;


uint32 rand32() {
	uint32 r = rand();
	r = r << 16;
	return r + rand();	
}


uint32 cotaInf(uint32 m_restantes, uint32 sum_x_n) {
	// supone que  a los siguientes les toca todas las aristas que puedan
	//              n
	// Sum_x_n = Sumatoria  ( j )
	//            j=nodo_x+1
	
	
	// el nodo actual tiene que usar las que sobran
	long aristas_sobrantes =  (long) m_restantes - (long) sum_x_n;
	
	if (aristas_sobrantes <= 0) {
		return 0;
	}
	else {
		return (uint32) aristas_sobrantes;
	}
}

uint32 cotaSup(uint32 nodo_x, uint32 m_restantes, uint32 n ) {
	// supone que a los siguientes nodos les toca una arista c/u
	uint32 max_aristas = m_restantes - (n - nodo_x);
	
	// pero no le pueden tocar mas aristas que la cantidad de nodos anteriores ( = label de nodo_x)
	if (nodo_x < max_aristas) {
		return nodo_x;
	}
	else {
		return max_aristas;	
	}
}

int main() {
	srand( time( 0 ) );

	int total = TOTAL;

	uint32 nodos = 2;
	while ( total-- ) {

		uint32 x=0, y, z;
		//uint32  nodos = 1 + rand32() % 60000;
		//uint32  aristas = (nodos-1) +  rand32() % (60000 - aristas+1);
		uint32 aristas = nodos*4;
		
		uint32 MAX_SUMA = 0x7FFFFFE;   // MAX_SUMA < 2^31

		uint32 SUMA = 0, MAX_PESO_ARISTA;
		cout << nodos << " " << aristas << '\n';			
		
		bool NEXT = true;
		uint32 aristas_x;
		uint32 sum_x_n = (nodos * (nodos - 1)) /2; 
		
		while (aristas) {
			
			// Genera peso Z
			MAX_PESO_ARISTA  = MAX_SUMA - (aristas - 1); 
			z = 1 + rand32() % MAX_PESO_ARISTA;

			
			// Genera aristas con extremo en X, y los une con nodos Y anteriores
			// El nodo Y es generado de forma aleatoria, pero consistente
						
				// Sigue con otro nodo: y genera la cantidad de aristas para ese nodo
			if (NEXT) {
				NEXT = false;
				x++;
				y=0;
				
				sum_x_n -= x;
				
				uint32 base = cotaInf(aristas, sum_x_n) + 1;
				uint32 offset = cotaSup(x,aristas, nodos) - cotaInf(aristas, sum_x_n);
				if (offset > 0)
					aristas_x =  base + rand32() % offset;
				else
					aristas_x = base;
							
			}

				// Genera un extremo
			if (!NEXT) {

				// si no sobran nodos, se recorre
				
				// si sobran nodos, elige al azar
				while ( !( rand32() % 2 ) && (aristas_x < (x-y)))
					y++;
										
				// usar ese nodo Y			
				aristas_x--;
									
			}

						
			cout << x << " " << y << " " << z << '\n';  
			y++;
			
			if (aristas_x == 0) NEXT = true;

			SUMA += z;
			MAX_SUMA -= z;
			aristas--;			
		}
		
		nodos++;
		
	}

	int a=0, b=0;
	cout << a << " " << b << '\n';

	return 0;
}
